第5期吐槽:经常OOM?吃内存元凶找到了:元数据缓存居然不能共享
文中参考文档点击阅读原文打开, 同时推荐2个学习环境:
1、懒人Docker镜像, 已打包200+插件:《最好的PostgreSQL学习镜像》
2、有web浏览器就能用的云起实验室: 《免费体验PolarDB开源数据库》
3、PolarDB开源数据库内核、最佳实践等学习图谱: https://www.aliyun.com/database/openpolardb/activity
第5期吐槽:老是OOM?吃内存元凶找到了!元数据缓存居然不共享
1、产品的问题点
meta cache (rel/catalog cache), plan cache是每个会话私有的内存.
2、问题点背后涉及的技术原理
正常的SQL执行过程包括sql parse, rewrite, plan, exec等几个过程, parse, rewrite, plan都比较耗费cpu, 在OLTP的短平快场景, 使用prepared statement可以避免每次调用都需要parse,rewrite,plan, 使用plan cache直接进入exec阶段(特定情况下的custom plan除外).
同时为了处理sql parse, rewrite, plan等, 数据库还需要一些meta cache, 例如访问过的表结构, 索引, 视图等定义.
plan cache和meta cache都是会话进程私有的.
PG 为每个会话分配一个backend process.
3、这个问题将影响哪些行业以及业务场景
SaaS行业
分区超多的, 而且使用长连接和绑定变量
微服务
4、会导致什么问题?
SaaS行业, 每个B端用户一套schema, 表超级多, 一个会话在整个生命周期内可能访问很多的数据库对象, 产生很多的plan cache、relcache, 单个会话对应的backend process占用大量内存. 进程多的话会导致内存消耗巨大, 导致OOM.
分区超多的, 而且使用长连接和绑定变量. 频繁更新的C端业务系统通常有这个特性, 例如共享单车, 单车数量多, 用户多, 需要通过分区提高垃圾回收和freeze的效率. 导致的问题同上.
微服务, 服务超级多, 导致与数据库的连接过多. 进而导致以上类似问题.
5、业务上应该如何避免这个坑
控制每个会话的生命周期, 从而避免长时间touch过多的relation, 导致内存爆增.
控制总连接数, 从而降低所有会话导致的整体内存使用.
使用高版本PG(大版本在逐渐优化)或pg_pathman, 避免即使只访问某个分区, 在plan过程依旧需要touch所有分区表.
使用pgbouncer连接池, 控制总连接数.
6、业务上避免这个坑牺牲了什么, 会引入什么新的问题
增加了复杂度, 很多初次使用PG的小伙伴不知道.
微服务很多的时候, 每个微服务至上的1个连接吧, 所以控制总连接数无解.
使用pgbouncer控制总连接的话必须使用statement或transaction level, 这样的话就不能使用prepared statement, 因为下次发起exec时可能已经不是之前那个backend process了.
7、数据库未来产品迭代如何修复这个坑
内置线程池
global cache (rel catalog caches, plan)
pg_backend_memory_contexts 查看内存上下文
文章中的参考文档请点击阅读原文获得.
欢迎关注我的github (https://github.com/digoal/blog) , 学习数据库不迷路.
近期正在写公开课材料, 未来将通过视频号推出, 欢迎关注视频号: